#define _CRT_SECURE_NO_WARNINGS

#include <Windows.h>
#include <iostream>
#include <time.h>
#include <mmsystem.h>

#include "resource.h"
#include "SuperString.h"

#define UPDATE_COUNTER	12345
#define TWENTY_SECS		1000
#define r ( ( rand() % 200 ) + 400)

LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );
VOID CALLBACK Timer( HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime );

int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, PSTR lpszCmdParam, int nCmdShow ) {
	static char	szAppName[] = "Wesley Maxey - Lab 1";
	HWND		hwnd;
	MSG			msg;
	WNDCLASSEX	wndclass;

	wndclass.cbSize			= sizeof(wndclass);
	wndclass.style			= CS_HREDRAW | CS_VREDRAW;
	wndclass.lpfnWndProc	= WndProc;
	wndclass.cbClsExtra		= 0;
	wndclass.cbWndExtra		= 0;
	wndclass.hInstance		= hInst;
	wndclass.hIcon			= LoadIcon( hInst, MAKEINTRESOURCE(IDI_ICON1) );
	wndclass.hCursor		= LoadCursor (NULL, IDC_ARROW);
	wndclass.hbrBackground	= WHITE_BRUSH;
	wndclass.lpszMenuName	= NULL;
	wndclass.lpszClassName	= szAppName;
	wndclass.hIconSm		= LoadIcon( hInst, MAKEINTRESOURCE(IDI_ICON1) );

	RegisterClassEx (&wndclass);

	hwnd = CreateWindow (szAppName,	// window class name
		"Maxey - Lab 4",			// window caption
		WS_OVERLAPPEDWINDOW,		// window style
		CW_USEDEFAULT,				// initial x position
		CW_USEDEFAULT,				// initial y position
		1200,						// initial x size
		800,						// initial y size
		NULL,						// parent window handle
		NULL,						// window menu handle
		hInst,						// program instance handle
		NULL);						// creation parameters

	ShowWindow (hwnd, nCmdShow);
	UpdateWindow (hwnd);

	while (GetMessage (&msg, NULL, 0, 0))
	{
		TranslateMessage (&msg);
		DispatchMessage (&msg);
	}
	return (int)(msg.wParam);
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
	HDC				hdc, hbdc;
	PAINTSTRUCT		ps;
	RECT			rect;
	RECT			trect;
	POINT			window;
	POINT			mouse;
	SYSTEMTIME		htime;
	DATE			hdate;
	SuperString		ss;

	static	HMENU	hmenu;
	static	char	buffer[51];
	static	int		length = 0;
	static	UINT	htimer = 1234;
	static	int		counter;
	static	bool	date = false, time = false;

	SHELLEXECUTEINFO hprog = {0};

	switch (message)
	{
	case WM_COMMAND:
		switch ( LOWORD(wParam) )
		{
		case ID_FILE_EXIT:
			SendMessage( hwnd, WM_CLOSE, NULL, NULL );
			break;
		case ID_FILE_CLEARBUFFER:
			length = 0;
			break;
		case ID_ANIMALS_CAT:
			MessageBox( hwnd, "KITTY!", "Cats", MB_OK );
			return 0;
		case ID_ANIMALS_DOG:
			MessageBox( hwnd, "Dog!", "Dogs", MB_OK );
			return 0;
		case ID_BREAK_SHAPES:
			if ( GetMenuState( hmenu, ID_BREAK_SHAPES, NULL ) & MF_CHECKED )
			{
				KillTimer( hwnd, htimer );
				CheckMenuItem( hmenu, ID_BREAK_SHAPES, MF_UNCHECKED );
				GetClientRect(hwnd, &rect);
				InvalidateRect( hwnd, &rect, false );
				counter = 0;
			}
			else
			{
				SetTimer( hwnd, htimer, 25, Timer );
				CheckMenuItem( hmenu, ID_BREAK_SHAPES, MF_CHECKED );
			}
			break;
		case ID_BREAK_SOUND:
			PlaySound( "sfile.wav", NULL, SND_ASYNC );
			break;
		case ID_DATE_CURRENTDATAE:
			if ( GetMenuState( hmenu, ID_DATE_CURRENTDATAE, NULL ) & MF_CHECKED )
			{
				CheckMenuItem( hmenu, ID_DATE_CURRENTDATAE, MF_UNCHECKED );
				GetClientRect(hwnd, &rect);
				InvalidateRect( hwnd, &rect, false );
				date = false;
			}
			else
			{
				CheckMenuItem( hmenu, ID_DATE_CURRENTDATAE, MF_CHECKED );
				GetClientRect(hwnd, &rect);
				InvalidateRect( hwnd, &rect, false );
				date = true;
			}
			break;
		case ID_DATE_CURRENTTIME:
			if ( GetMenuState( hmenu, ID_DATE_CURRENTTIME, NULL ) & MF_CHECKED )
			{
				CheckMenuItem( hmenu, ID_DATE_CURRENTTIME, MF_UNCHECKED );
				GetClientRect(hwnd, &rect);
				InvalidateRect( hwnd, &rect, false );
				time = false;
			}
			else
			{
				CheckMenuItem( hmenu, ID_DATE_CURRENTTIME, MF_CHECKED );
				GetClientRect(hwnd, &rect);
				InvalidateRect( hwnd, &rect, false );
				time = true;
			}
			break;
		case ID_HELP_SYSTEMINFO:
			/*HAHA Lazy get system metrics. Here is a nice modal way to display that info
			by opening the built in windows DXDIAG window. Let's the user see everything.*/
			hprog.cbSize		= sizeof(SHELLEXECUTEINFO);
			hprog.fMask			= SEE_MASK_NOCLOSEPROCESS;
			hprog.hwnd			= NULL;
			hprog.lpVerb		= "open";
			hprog.lpFile		= "dxdiag";
			hprog.lpParameters	= NULL;
			hprog.nShow			= SW_SHOW;
			hprog.hInstApp		= NULL;

			ShellExecuteEx( &hprog );

			/*Window is a little unresponsive afterwards, but it's only because
			//of the weak OS interface between processes*/
			WaitForSingleObject( hprog.hProcess, INFINITE );
			break;
		case ID_HELP_ABOUT:
			MessageBox( hwnd, "I made this! \n	Wesley Maxey", "Yeah! Stuff!", MB_OK );
			break;
		}

		return 0;
	case WM_CREATE:
		hmenu = LoadMenu(NULL, MAKEINTRESOURCE(IDR_MENU1) );

        SetMenu(hwnd, hmenu);

		break;

	case WM_PAINT:
		GetClientRect( hwnd, &rect );
		GetLocalTime( &htime );

		hdc = BeginPaint( hwnd, &ps );
		
		FillRect( hdc, &rect, WHITE_BRUSH );
		if ( counter )
		{
			Rectangle( hdc, r, r, r, r );
			Ellipse( hdc, r, r, r, r );
		}

		SetTextAlign( hdc, TA_LEFT | TA_BOTTOM );
		TextOut( hdc, 0, rect.bottom - 20, buffer, length );

		SetTextAlign( hdc, TA_CENTER );
		if ( date )
		{
		ss.setString( htime.wDay, "/", htime.wMonth, "/", htime.wYear );
		TextOut( hdc, rect.right / 2, (rect.bottom / 2) + 10, ss.getString(), strlen(ss.getString()) );
		}

		if ( time )
		{
		ss.setString( htime.wHour, ":", htime.wMinute, ":", htime.wSecond );
		TextOut( hdc, rect.right / 2, (rect.bottom / 2) - 10, ss.getString(), strlen(ss.getString()) );
		}

		EndPaint( hwnd, &ps );

		break;

	case WM_SIZE:
		GetClientRect(hwnd, &rect);
		InvalidateRect( hwnd, &rect, false );
		return 0;

	case WM_MOVE:
		GetClientRect(hwnd, &rect);
		InvalidateRect( hwnd, &rect, false );
		return 0;

	case WM_CHAR:
		buffer[++length] = wParam;
		if ( length > 48 )
		{
			length = 48;
			strcpy( buffer, buffer + 1 );
		}
		GetClientRect(hwnd, &rect);
		InvalidateRect( hwnd, &rect, false );
		return 0;

	case WM_QUIT:
		break;

	case WM_DESTROY:
		DestroyMenu( hmenu );
		PostQuitMessage(0);
		return 0;

	case WM_MOUSEMOVE:
		return 0;

	case WM_KEYDOWN:
		break;

	case UPDATE_COUNTER:
		if ( counter >= TWENTY_SECS )
		{
			counter = 0;
			KillTimer( hwnd, htimer );
			CheckMenuItem( hmenu, ID_BREAK_SHAPES, MF_UNCHECKED );
		}				
		else
			counter++;
	}

	return DefWindowProc (hwnd, message, wParam, lParam);
}

//Timer function that sends a message to the window (Wanted to demonstrate a seperate callback function)
VOID CALLBACK Timer( HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime ) {
	RECT	rect;
	GetClientRect(hwnd, &rect);
	InvalidateRect( hwnd, &rect, false );
	SendMessage( hwnd, UPDATE_COUNTER, NULL, NULL );
}